package org.moon.framework.autoconfigure.log;

import com.google.common.collect.Maps;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.moon.framework.autoconfigure.MoonConstants;
import org.moon.framework.autoconfigure.config.SpringContextConfig;
import org.moon.framework.autoconfigure.log.domain.ErrorLogger;
import org.moon.framework.autoconfigure.secure.AuthUtils;
import org.moon.framework.autoconfigure.secure.domain.AuthInfo;
import org.moon.framework.autoconfigure.utils.Func;
import org.moon.framework.autoconfigure.utils.IpUtils;
import org.moon.framework.autoconfigure.utils.JsonUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

/**
 * 错误日志发送
 * 将错误日志统一都发送到redis  list队列中，统一由moon-admin服务入库
 */
public class ErrorLogHandler {

    public static void sendErrorLog2queue(String applicationName,Throwable t){
        ErrorLogger errorLog = new ErrorLogger();
        // 设置异常字段
        errorLog.setExceptionName(t.getClass().getName());
        errorLog.setExceptionMessage(ExceptionUtils.getMessage(t));
        errorLog.setExceptionRootCauseMessage(ExceptionUtils.getRootCauseMessage(t));
        errorLog.setExceptionStackTrace(ExceptionUtils.getStackTrace(t));
        StackTraceElement[] stackTraceElements = t.getStackTrace();
        Assert.notEmpty(stackTraceElements, "异常 stackTraceElements 不能为空");
        StackTraceElement stackTraceElement = stackTraceElements[0];
        errorLog.setExceptionClassName(stackTraceElement.getClassName());
        errorLog.setExceptionFileName(stackTraceElement.getFileName());
        errorLog.setExceptionMethodName(stackTraceElement.getMethodName());
        errorLog.setExceptionLineNumber(stackTraceElement.getLineNumber());
        // 设置其它字段
        errorLog.setRequestId(AuthUtils.getRequestId());
        errorLog.setApplicationName(applicationName);
        HttpServletRequest request = Func.getRequest();
        if(request!=null){
            errorLog.setRequestUrl(request.getRequestURI());
            Map<String, Object> requestParams = Maps.newHashMap();
            requestParams.put("query", Func.getParamMap(request));
            requestParams.put("body", Func.getBody(request));
            errorLog.setRequestParams(JsonUtils.obj2string(requestParams));
            errorLog.setRequestMethod(request.getMethod());
        }
        errorLog.setRequestFrom(AuthUtils.getRequestFrom());
        errorLog.setUserAgent(Func.getUserAgent());
        errorLog.setUserIp(IpUtils.getIpAddr());
        errorLog.setExceptionTime(new Date());

        // 处理用户信息
        AuthInfo info = AuthUtils.getAuthInfo();
        if(info.getId()!=null){
            errorLog.setNickName(info.getNickName());
            errorLog.setCreateBy(info.getId());
            errorLog.setCreateTime(new Date());
            errorLog.setCreateDept(info.getDeptId());
            errorLog.setTenantCode(info.getTenantCode());
            errorLog.setUpdateBy(info.getId());
            errorLog.setUpdateTime(new Date());
        }
        //此处只能通过名称获取，因为 StringRedisTemplate继承了RedisTemplate,如果通过类型获取则会拿到两个Bean
        RedisTemplate redisTemplate = SpringContextConfig.getBean("redisTemplate");
        redisTemplate.opsForList().rightPush(MoonConstants.REDIS_KEY_ERROR_LOG,errorLog);
    }
}
